# VPI with mingw64 gcc makefile scripts and rules.

# Verbose
ifeq ($(USE_VERBOSE_COMPILE),yes)
  Q :=
  ECHO := @true
else
  Q := @
  ECHO := @echo
endif

# Automatic compiler options
OPT = $(USE_OPT)
COPT = $(USE_COPT)
CPPOPT = $(USE_CPPOPT)

# Data flags
OPT += -xc -fno-strict-aliasing -fno-builtin -funsigned-char -fshort-enums -fshort-wchar

# Garbage collection
ifeq ($(USE_LINK_GC),yes)
  OPT += -ffunction-sections -fdata-sections -fno-common
  LDOPT :=
else
  LDOPT :=
endif

# Linker extra options
ifneq ($(USE_LDOPT),)
  LDOPT := $(LDOPT),$(USE_LDOPT)
endif

# Link time optimizations
ifeq ($(USE_LTO),yes)
  OPT += -flto
  LDOPT := --lto
endif

# FPU-related options
ifeq ($(USE_FPU),)
  USE_FPU = no
endif

# Output directory and files
ifeq ($(BUILDDIR),)
  BUILDDIR = build
endif
ifeq ($(BUILDDIR),.)
  BUILDDIR = build
endif
OUTFILES = $(BUILDDIR)/$(PROJECT).vpi

# Source files groups and paths
SRC	      = $(CSRC)$(CPPSRC)
SRCPATHS  = $(sort $(dir $(ASMXSRC)) $(dir $(ASMSRC)) $(dir $(SRC)))

# Various directories
OBJDIR    = $(BUILDDIR)/obj
LSTDIR    = $(BUILDDIR)/lst

# Object files groups
CXOBJS    = $(addprefix $(OBJDIR)/, $(notdir $(CXSRC:.c=.o)))
COBJS     = $(addprefix $(OBJDIR)/, $(notdir $(CSRC:.c=.o)))
CPPOBJS   = $(addprefix $(OBJDIR)/, $(notdir $(CPPSRC:.cpp=.o)))
ASMOBJS   = $(addprefix $(OBJDIR)/, $(notdir $(ASMSRC:.s=.o)))
ASMXOBJS  = $(addprefix $(OBJDIR)/, $(notdir $(ASMXSRC:.s=.o)))
OBJS	  = $(ASMXOBJS) $(ASMOBJS) $(CXOBJS) $(COBJS) $(CPPOBJS)

# Paths
IINCDIR = $(patsubst %,-I%,$(INCDIR) $(DINCDIR) $(UINCDIR))
LLIBDIR = $(patsubst %,-L%,$(DLIBDIR) $(ULIBDIR))

# Macros
DEFS    = $(DDEFS) $(UDEFS)
ADEFS   = $(DADEFS) $(UADEFS)

# Libs
LIBS    = $(DLIBS) $(ULIBS)

# Various settings
MCFLAGS   = $(shell iverilog-vpi --cflags)
ODFLAGS	  = -h -x --syms -S
ASFLAGS   = $(MCFLAGS) $(OPT) -Wa,-amhls=$(LSTDIR)/$(notdir $(<:.S=.lst)) $(ADEFS)
ASXFLAGS  = $(MCFLAGS) $(OPT) -Wa,-amhls=$(LSTDIR)/$(notdir $(<:.S=.lst)) $(ADEFS)
CFLAGS    = $(MCFLAGS) $(OPT) $(COPT) $(CWARN) -Wa,-alms=$(LSTDIR)/$(notdir $(<:.c=.lst)) $(DEFS)
CPPFLAGS  = $(MCFLAGS) $(OPT) $(CPPOPT) $(CPPWARN) -Wa,-alms=$(LSTDIR)/$(notdir $(<:.cpp=.lst)) $(DEFS)
LDFLAGS   = $(MCFLAGS) $(OPT) -nostartfiles $(LLIBDIR) -Wl,-Map=$(BUILDDIR)/$(PROJECT).map,--cref,--no-warn-mismatch,--library-path=$(RULESPATH),--script=$(LDSCRIPT)$(LDOPT)

# Generate dependency information
ASFLAGS  += --depend .dep/$(@F).d
CFLAGS   += -MD -MP -MF .dep/$(basename $(@F)).d
CPPFLAGS += -MD -MP -MF .dep/$(@F).d

# Paths where to search for sources
VPATH     = $(SRCPATHS)

#
# Makefile rules
#

all: PRE_MAKE_ALL_RULE_HOOK $(OBJS) $(OUTFILES) POST_MAKE_ALL_RULE_HOOK

PRE_MAKE_ALL_RULE_HOOK:

POST_MAKE_ALL_RULE_HOOK:

$(OBJS): | $(BUILDDIR) $(OBJDIR) $(LSTDIR)

$(BUILDDIR) $(OBJDIR) $(LSTDIR):
	$(ECHO) Compiler Options
	$(ECHO) $(CC) -c $(CFLAGS) -I. $(IINCDIR) main.c -o main.o
	$(ECHO)
	mkdir -p $(OBJDIR)
	mkdir -p $(LSTDIR)

$(LDSCRIPT): $(SAGSCRIPT)
	$(Q)$(SAG) $(SAGSCRIPT) -o $(LDSCRIPT)

$(CPPOBJS) : $(OBJDIR)/%.o : %.cpp Makefile
	$(ECHO) Compiling $(<F)
	$(Q)$(CPPC) -c $(CPPFLAGS) -I. $(IINCDIR) $< -o $@

$(COBJS) : $(OBJDIR)/%.o : %.c Makefile
	$(ECHO) Compiling $(<F)
	$(Q)$(CC) -c $(CFLAGS) -I. $(IINCDIR) $< -o $@

$(CXOBJS) : $(OBJDIR)/%.o : %.c Makefile
	$(ECHO) Compiling $(<F)
	$(Q)$(CC) -c $(CFLAGS) -fno-lto -I. $(IINCDIR) $< -o $@

$(ASMOBJS) : $(OBJDIR)/%.o : %.s Makefile
	$(ECHO) Compiling $(<F)
	$(Q)$(AS) $(ASFLAGS) -I. $(IINCDIR) $< -o $@

$(ASMXOBJS) : $(OBJDIR)/%.o : %.s Makefile
	$(ECHO) Compiling $(<F)
	$(Q)$(CC) $(ASXFLAGS) -I. $(IINCDIR) $< -o $@

%.vpi: $(OBJS)
	$(ECHO) Linking $@
	iverilog-vpi -mingw=$(MINGW) --name=$(PROJECT) $(OBJS)

%.exe: $(OBJS)
	$(ECHO) Linking $@
	$(Q)$(CC) $(OBJS) $(LIBS) -o $@

%.a: $(OBJS)
	$(ECHO) Creating $@
	$(Q)$(AR) $(ARFLAGS) $@ $(OBJS) > /dev/null

%.hex: %.exe $(LDSCRIPT)
	$(ECHO) Creating $@
	$(Q)$(HEX) $< --output $@

%.bin: %.exe $(LDSCRIPT)
	$(ECHO) Creating $@
	$(Q)$(BIN) $< --output $@

%.txt: %.axf $(LDSCRIPT)
	$(ECHO) Creating $@
	$(Q)$(ELF) -d -e -c $< -o $@

clean:
	$(ECHO) Cleaning
	-rm -fR .dep $(BUILDDIR)
	$(ECHO) Done

rebuild: clean all

#
# Include the dependency files, should be the last of the makefile
#
-include $(shell mkdir .dep 2>/dev/null) $(wildcard .dep/*)

# *** EOF ***
